package com.sprouting.ops.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sprouting.ops.annotations.invoke.IdempotentSingle;
import com.sprouting.ops.interfaces.AddGroup;
import com.sprouting.ops.interfaces.ConstantBase;
import com.sprouting.ops.interfaces.ConstantPower;
import com.sprouting.ops.interfaces.UpdGroup;
import com.sprouting.ops.model.OpsAuthority;
import com.sprouting.ops.model.OpsRoleAuthority;
import com.sprouting.ops.model.ResultJson;
import com.sprouting.ops.model.vo.PowerTree;
import com.sprouting.ops.model.vo.UserOwnRoleVo;
import com.sprouting.ops.service.OpsAuthorityService;
import com.sprouting.ops.service.OpsRoleAuthorityService;
import com.sprouting.ops.service.OpsRoleService;
import com.sprouting.ops.utils.CheckTool;
import com.sprouting.ops.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (Power)表控制层
 *
 * @author longx
 * @since 2023-03-19 22:44:34
 */
@Slf4j
@RestController
@RequestMapping("power")
public class OpsAuthorityController {

    @Autowired
    private OpsAuthorityService opsAuthorityService;
    @Autowired
    private OpsRoleAuthorityService opsRoleAuthorityService;
    @Resource
    private OpsRoleService opsRoleService;


    /**
     * 获取指定角色的所有的权限ID
     * @return
     */
    @PostMapping("getAuthByRoleId")
    public ResultJson getAuthByRoleId(String roleId){
        if (CheckTool.checkNull(roleId)){
            return ResultJson.errorCheck();
        }
        // 角色如果是超级管理员，则要查询出全部
        if (ConstantPower.Base.BASE_ROLE_ID.equals(roleId)){
            List<OpsAuthority> list = opsAuthorityService.list();
            if (CollUtil.isEmpty(list)){
                return ResultJson.success();
            }
            List<String> collect = list.stream().map(OpsAuthority::getId).collect(Collectors.toList());
            return ResultJson.success(collect);
        }

        return ResultJson.success(opsRoleAuthorityService.getAuthByRoleId(roleId));
    }

    /**
     * 获取可添加的权限(管理员获取全部权限)
     * 其他角色获取自己有的权限
     * 人员的权限必须从最基础的权限开始
     * @return
     */
    @PostMapping("getAvailableForAuth")
    public ResultJson getAvailableForAuth(){
        if (StpUtil.hasRole(ConstantPower.Base.BASE_ROLE_CODE)){
            List<OpsAuthority> list = opsAuthorityService.list();
            List<PowerTree> treeList = BeanUtil.copyToList(list, PowerTree.class);
            return ResultJson.success(buildTree(treeList));
        }

        List<UserOwnRoleVo> list = opsRoleService.getUserOwnRole(StpUtil.getLoginIdAsString());
        if (CollUtil.isEmpty(list)){
            return ResultJson.success();
        }
        List<String> roleIdList = list.stream().map(UserOwnRoleVo::getId).collect(Collectors.toList());
        List<OpsAuthority> authList = opsAuthorityService.getByRoleIdBatch(roleIdList);
        List<PowerTree> treeList = BeanUtil.copyToList(authList, PowerTree.class);
        return ResultJson.success(buildTree(treeList));
    }

    /**
     * 获取权限树
     * 全部展示，只有管理员才有这个权限访问即可
     * @return
     */
    // @DataScope(fieldName = "create_id")
    @PostMapping("getPowerTree")
    public ResultJson<List<PowerTree>> getPowerTree(){
        List<OpsAuthority> opsAuthorityList = opsAuthorityService.list();
        if (CollUtil.isEmpty(opsAuthorityList)){
            return ResultJson.success();
        }

        List<PowerTree> powerAllList = BeanUtil.copyToList(opsAuthorityList, PowerTree.class);
        List<PowerTree> tree = buildTree(powerAllList);
        return ResultJson.success(tree);
    }

    /**
     * 获取当前用户拥有的权限-直接从缓存中获取的权限码
     * @return
     */
    @PostMapping("getPower")
    public ResultJson<List<String>> getPower(){
        return ResultJson.success(StpUtil.getPermissionList());
        // return ResultJson.success(stpInterface.getPermissionList(StpUtil.getLoginId(), null));
    }

    /**
     * 当前账号是否含有指定权限标识
     * @return true 拥有 false 不拥有
     */
    @PostMapping("hasPower")
    public ResultJson<Boolean> hasPower(String power){
        return ResultJson.success(StpUtil.hasPermission(power));
    }

    /**
     * 当前账号是否含有指定权限 [指定多个，必须全部验证通过]
     * @param powerList 要查询的权限
     * @return true 拥有 false 不拥有
     */
    @PostMapping("checkPowerAnd")
    public ResultJson<Boolean> checkPowerAnd(@RequestParam(name = "powerList", required = false) List<String> powerList){
        if (powerList == null || powerList.size() == 0){
            return ResultJson.errorCheck();
        }

        try {
            StpUtil.checkPermissionAnd(powerList.toArray(new String[0]));
        } catch (NotPermissionException e) {
            return ResultJson.success(false);
        }

        return ResultJson.success(true);
    }

    /**
     * 当前账号是否含有指定权限 [指定多个，只要其一验证通过即可]
     * @param powerList 要查询的权限
     * @return true 拥有 false 不拥有
     */
    @PostMapping("checkPowerOr")
    public ResultJson<Boolean> checkPowerOr(@RequestParam(name = "powerList", required = false) List<String> powerList){
        if (powerList == null || powerList.size() == 0){
            return ResultJson.errorCheck();
        }

        try {
            StpUtil.checkPermissionOr(powerList.toArray(new String[0]));

        } catch (NotPermissionException e) {
            return ResultJson.success(false);
        }

        return ResultJson.success(true);
    }

    /**
     * 保存权限
     * @param power 权限
     * @return
     */
    @IdempotentSingle
    @PostMapping("savePower")
    @SaCheckPermission(ConstantPower.Power.SAVE)
    public ResultJson savePower(@Validated(AddGroup.class) OpsAuthority power){
        String msg = checkPower(power);
        if (msg != null){
            return ResultJson.error(msg);
        }

        // 处理上级
        String parentMsg = addParent(power);
        if (parentMsg != null){
            return ResultJson.error(parentMsg);
        }
        power.setId(IdTool.getId());
        opsAuthorityService.save(power);
        return ResultJson.success(power);
    }

    /**
     * 更新权限
     * @param power 权限
     * @return
     */
    @IdempotentSingle
    @PostMapping("updPower")
    @SaCheckPermission(ConstantPower.Power.UPD)
    public ResultJson updPower(@Validated(UpdGroup.class) OpsAuthority power){
        String msg = checkPower(power);
        if (msg != null){
            return ResultJson.error(msg);
        }

        OpsAuthority auth = opsAuthorityService.getById(power.getId());
        if (auth == null){
            return ResultJson.errorCheck();
        }
        if (ConstantPower.Base.BASE_AUTH_ID.equals(auth.getId())){
            return ResultJson.error("超级权限无法修改");
        }

        power.setParentIds(null);
        power.setParentId(null);
        opsAuthorityService.updateById(power);
        return ResultJson.success();
    }

    /**
     * 删除权限
     * @param id 权限id
     * @return
     */
    @IdempotentSingle
    @PostMapping("delPower")
    public ResultJson delPower(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorCheck();
        }

        OpsAuthority auth = opsAuthorityService.getById(id);
        if (auth == null){
            return ResultJson.success();
        }
        if (ConstantPower.Base.BASE_AUTH_ID.equals(auth.getId())){
            return ResultJson.error("超级权限无法删除");
        }

        LambdaQueryWrapper<OpsRoleAuthority> roleAuthWrapper = new LambdaQueryWrapper<>();
        roleAuthWrapper.eq(OpsRoleAuthority::getAuthorityId, id);
        OpsRoleAuthority roleAuthority = opsRoleAuthorityService.getOne(roleAuthWrapper);
        if (roleAuthority != null){
            return ResultJson.error("权限已绑定，请先删除对应角色");
        }

        opsAuthorityService.delPower(id);
        return ResultJson.success();
    }

    /**
     * 添加上级
     * @param auth 权限
     * @return 非null则添加的时候出错了
     */
    private String addParent(OpsAuthority auth){
        if (ConstantBase.DefaultValue.STRING.equals(auth.getParentId())){
            // 最上级
        } else {
            // 存在上级
            OpsAuthority parent = opsAuthorityService.getById(auth.getParentId());
            if (parent == null){
                log.error("上级节点错误，不存在的上级。{}", auth.getParentId());
                return "非法上级节点";
            }

            if (StrUtil.isEmpty(parent.getParentIds())){
                // 上级节点是顶级节点，没有上级，直接填上级即可
                auth.setParentIds(parent.getId());
            } else {
                auth.setParentIds(parent.getParentIds() + "," + parent.getId());
            }
        }

        return null;
    }

    /**
     * 校验权限
     * @param power 权限
     * @return 非null则有异常
     */
    private String checkPower(OpsAuthority power){
        OpsAuthority db = opsAuthorityService.getByPermission(power.getId(), power.getCode());
        if (db != null){
            return "权限标识符已使用";
        }
        if (ConstantBase.DefaultValue.STRING.equals(power.getParentId())){
            // 顶级节点不需要验证
            return "顶级节点不允许新增权限";
        } else {
            // 子节点
            OpsAuthority parent = opsAuthorityService.getById(power.getParentId());
            if (parent == null){
                return "无效的上级节点";
            }
        }

        return null;
    }

    /**
     * 构建生成权限树
     * @param powerAllList 所有权限
     * @return 生成的树
     */
    private List<PowerTree> buildTree(List<PowerTree> powerAllList){
        if (CollUtil.isEmpty(powerAllList)){
            return null;
        }
        // 获取到根节点
        List<PowerTree> rootPowerList = powerAllList.stream().filter(i -> ConstantBase.DefaultValue.STRING.equals(i.getParentId())).sorted(Comparator.comparing(PowerTree::getType)).collect(Collectors.toList());
        if (rootPowerList.isEmpty()){
            log.error("[权限] 当前权限树异常，未查询到当前系统顶级节点!用户ID->{}", StpUtil.getLoginId());
            return null;
        }

        for (PowerTree powerTree : rootPowerList){
            getChild(powerTree, powerAllList);
        }

        return rootPowerList;
    }

    /**
     * 获取权限子节点
     * @param powerTree 当前权限
     * @param powerList 全部权限
     */
    private void getChild(PowerTree powerTree, List<PowerTree> powerList){
        List<PowerTree> childList = powerList.stream().filter(obj -> powerTree.getId().equals(obj.getParentId())).sorted(Comparator.comparing(PowerTree::getType)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(childList)){
            powerTree.setChildren(childList);
            for (PowerTree power : childList){
                power.setParentName(powerTree.getName());
                getChild(power, powerList);
            }
        }
    }
}

